"""
@Desc: 因子模型策略的流程
因子选择：
    选择一组能够解释资产收益的因子，例如：
    价值因子：市盈率（PE）、市净率（PB）。
    动量因子：过去12个月的收益率。
    质量因子：ROE（净资产收益率）、资产负债率。
    规模因子：市值（Market Cap）。
数据获取：
    获取股票的历史价格、财务数据和因子数据。
因子处理：
    对因子进行标准化、去极值、中性化等处理。
因子加权：
    根据因子的重要性赋予权重，构建综合因子得分。
选股与组合构建：
    根据因子得分选择股票，构建投资组合。
回测与绩效评估：
    在历史数据上测试策略表现，评估收益和风险。

多因子选股策略
以下是一个基于**价值因子（PE）和动量因子（过去12个月收益率）**的多因子选股策略示例。

@Auth: meihongliang-m2
@Date: 2025/3/18-16:08
"""
import pandas as pd
import numpy as np
import yfinance as yf
from matplotlib import pyplot as plt
from sklearn.preprocessing import StandardScaler


# 1. 获取数据
def get_data(tickers, start_date, end_date):
    data = yf.download(tickers, start=start_date, end=end_date)
    return data['Adj Close']


# 2. 计算因子
def calculate_factors(data, tickers):
    factors = pd.DataFrame(index=tickers)

    # 价值因子：市盈率（PE）
    factors['PE'] = [np.random.uniform(5, 20) for _ in tickers]  # 模拟PE数据

    # 动量因子：过去12个月收益率
    factors['Momentum'] = (data.iloc[-1] - data.iloc[-252]) / data.iloc[-252]

    return factors


# 3. 因子处理
def process_factors(factors):
    # 标准化因子
    scaler = StandardScaler()
    factors_scaled = pd.DataFrame(scaler.fit_transform(factors), columns=factors.columns, index=factors.index)
    return factors_scaled


# 4. 因子加权
def calculate_factor_score(factors_scaled, weights):
    factors_scaled['Factor_Score'] = factors_scaled.dot(weights)  # 计算综合因子得分
    return factors_scaled


# 5. 选股
def select_stocks(factors_scaled, top_n=10):
    selected_stocks = factors_scaled.nlargest(top_n, 'Factor_Score')  # 选择因子得分最高的股票
    return selected_stocks


# 6. 回测
def backtest(data, selected_stocks, start_date, end_date):
    portfolio_returns = data[selected_stocks.index].pct_change().mean(axis=1)  # 等权投资组合收益率
    portfolio_returns = portfolio_returns[
        (portfolio_returns.index >= start_date) & (portfolio_returns.index <= end_date)]
    cumulative_returns = (1 + portfolio_returns).cumprod()  # 累计收益
    return cumulative_returns


# 7. 可视化结果
def plot_results(cumulative_returns):
    plt.figure(figsize=(10, 6))
    plt.plot(cumulative_returns, label='Portfolio Cumulative Returns')
    plt.title('Factor Model Strategy Performance')
    plt.xlabel('Date')
    plt.ylabel('Cumulative Returns')
    plt.legend()
    plt.show()


# 主程序
if __name__ == "__main__":
    # 参数设置
    tickers = ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'TSLA', 'META', 'NVDA', 'BRK-B', 'JNJ', 'WMT']  # 股票池
    start_date = '2020-01-01'
    end_date = '2023-01-01'
    weights = {'PE': -0.5, 'Momentum': 0.5}  # 因子权重（PE越低越好，动量越高越好）
    top_n = 5  # 选股数量

    # 获取数据
    data = get_data(tickers, start_date, end_date)
    # 计算因子
    factors = calculate_factors(data, tickers)
    # 因子处理
    factors_scaled = process_factors(factors)
    # 因子加权
    factors_scaled = calculate_factor_score(factors_scaled, weights)
    # 选股
    selected_stocks = select_stocks(factors_scaled, top_n)
    print("Selected Stocks:\n", selected_stocks)

    # 回测
    cumulative_returns = backtest(data, selected_stocks, start_date, end_date)
    # 可视化结果
    plot_results(cumulative_returns)
